﻿using System;
using System.Collections.Generic;
using System.Linq;
using roster.Domain;

namespace roster.UI
{
    public class RosterController
    {
        private ILootList m_LootList;
        private readonly ICreateRosterController m_CreateRosterController;
        private readonly IPlayerController m_PlayerController;
        private readonly IPlayerSelectionController m_PlayerSelectionController;
        private readonly IRaidController m_RaidController;
        private readonly IRosterView m_RosterView;
        private readonly RaidCreationController m_RaidCreationController;

        public event EventHandler Closed;

        public RosterController(IRosterView rosterView, IPlayerController playerController,
                                IRaidController raidController,
                                IPlayerSelectionController playerSelectionController,
                                ICreateRosterController createRosterController)
        {
            m_RosterView = rosterView;
            m_CreateRosterController = createRosterController;
            m_PlayerSelectionController = playerSelectionController;
            m_PlayerController = playerController;
            m_RaidController = raidController;

            m_PlayerController.AddPlayer += m_PlayerController_AddPlayer;
            m_CreateRosterController.CreateRoster += m_CreateRosterController_CreateRoster;

            m_RaidCreationController = new RaidCreationController(new RaidCreationView());
            m_RaidCreationController.RaidCreated += m_RaidCreationController_RaidCreated;

            ConfigureRaidView();
            ConfigureRaidController();
        }

        private void ConfigureRaidController()
        {
            m_RaidController.EndRaid += m_RaidController_EndRaid;
            m_RaidController.AddPlayer += m_RaidController_AddPlayer;
        }

        private void ConfigureRaidView()
        {
            m_RosterView.Closed += delegate { Closed(this, null); };
            m_RosterView.AddPlayer += m_RosterView_AddPlayer;
            m_RosterView.Remove += m_RosterView_RemovePlayer;
            m_RosterView.MoveUp += m_RosterView_MoveUp;
            m_RosterView.MoveDown += m_RosterView_MoveDown;
            m_RosterView.CreateRaid += m_RosterView_CreateRaid;
            m_RosterView.CreateRaidFromFile += m_RosterView_CreateRaidFromFile;
            m_RosterView.LoadRoster += m_RosterView_LoadRoster;
            m_RosterView.SaveRoster += m_RosterView_SaveRoster;
            m_RosterView.Randomize += m_RosterView_Randomize;
            m_RosterView.CreateRoster += m_RosterView_CreateRoster;
        }

        private void m_CreateRosterController_CreateRoster(string rosterName)
        {
            SetTitles(rosterName);
            m_LootList = new LootList();
            m_RosterView.EnableAction();
            UpdateRosterView();
        }

        private void m_RosterView_CreateRoster()
        {
            m_CreateRosterController.Display();
        }

        private void m_RaidController_AddPlayer(IEnumerable<IPlayer> players)
        {
            m_RaidController.InsertPlayers(
                m_PlayerSelectionController.GetPlayer(m_LootList.Where(x => !players.Contains(x))));
        }

        private void m_RosterView_RemovePlayer(IPlayer player)
        {
            m_LootList.RemovePlayer(player);
            UpdateRosterView();
        }

        private void m_PlayerController_AddPlayer(IPlayer player)
        {
            m_LootList.AddPlayer(player);
            UpdateRosterView();
        }

        private void m_RosterView_Randomize()
        {
            m_LootList.Randomize();
            UpdateRosterView();
        }

        public void m_RosterView_SaveRoster(string fileName)
        {
            new PlayerFile(fileName).WritePlayers(new RosterDetails(m_RosterView.Title, m_LootList));
        }

        public void m_RosterView_LoadRoster(string fileName)
        {
            var rosterDetails = new PlayerFile(fileName).GetPlayers();
            m_LootList = new LootList(rosterDetails.Players);
            SetTitles(rosterDetails.Title);
            m_RosterView.EnableAction();
            UpdateRosterView();
        }

        private void SetTitles(string title)
        {
            m_RosterView.Title = title;
            m_RaidController.SetTitle(title);
        }

        private void m_RosterView_MoveDown(IPlayer player)
        {
            m_LootList.MovePlayerDown(player);
            UpdateRosterView(player);
        }

        private void UpdateRosterView(IPlayer player)
        {
            UpdateRosterView();
            m_RosterView.SelectPlayer(player);
        }

        private void m_RosterView_MoveUp(IPlayer player)
        {
            m_LootList.MovePlayerUp(player);
            UpdateRosterView(player);
        }

        private void m_RosterView_CreateRaid(IEnumerable<IPlayer> players)
        {
            m_RaidController.StartRaid(players);
            m_RosterView.HideView();
        }
        
        private void m_RosterView_CreateRaidFromFile(string fileName)
        {
        	IRaidFileReader reader = RaidFileRegistrar.Instance.GetReader(fileName);

        	IEnumerable<IPlayer> players = reader.ReadFile(fileName);

        	m_RaidCreationController.CreateRaid(new List<IPlayer>(m_LootList.Players), players);
        }

        private void m_RaidController_EndRaid(IEnumerable<IPlayer> players)
        {
            m_LootList.Update(players);
            players.UpdateAttendance();
            UpdateRosterView();
            Show();
        }

        private void m_RosterView_AddPlayer()
        {
            m_PlayerController.GetPlayer();
        }

        private void UpdateRosterView()
        {
            m_RosterView.UpdateView(m_LootList);
        }

        public void Show()
        {
            m_RosterView.Show();
        }
        
        private void m_RaidCreationController_RaidCreated(IEnumerable<IPlayer> players)
        {
        	m_LootList.Update(players);

        	m_RosterView.HideView();
        	m_RaidController.StartRaid(players);
        }
    }
}